#ifndef __MY_UTIL__
#define __MY_UTIL__

#include <iostream>
#include <cstdio>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fstream>
#include <experimental/filesystem>
#include <memory>
#include <sstream>
#include <vector>

namespace hhbcloud
{

    class FileUtil
    {
    public:
        FileUtil(const std::string& filename)
            :_filename(filename)
        {
        }

        bool Remove()
        {
            if (remove(_filename.c_str()) == 0)
            {
                return true;
            }
            return false;
        }

        // 获取文件大小
        size_t FileSize()
        {
            struct stat st;
            if (stat(_filename.c_str(), &st) < 0)
            {
                std::cout << "get file size error" << std::endl;
                return -1;
            }

            return st.st_size;
        }
        time_t LastMTime()
        {
            struct stat st;
            if (stat(_filename.c_str(), &st) < 0)
            {
                std::cout << "get lastmtime error" << std::endl;
                return -1;
            }

            return st.st_mtime;
        }

        time_t LastATime()
        {
            struct stat st;
            if (stat(_filename.c_str(), &st) < 0)
            {
                std::cout << "get lastatime error" << std::endl;
                return -1;
            }

            return st.st_atime;
        }

        // 获取文件路径中的文件名称
        std::string FileName()
        {
            size_t pos = _filename.find_last_of("\\");
            if (pos == std::string::npos)
            {
                // 此时没有找到/说明文件路径就是文件名称
                return _filename;
            }

            return _filename.substr(pos + 1);
        }


        // 设置文件内容
        bool SetContent(const std::string& body)
        {
            // 打开文件
            std::ofstream ofs;
            ofs.open(_filename, std::ios::binary);
            if (ofs.is_open() == false)
            {
                std::cout << "write open file error" << std::endl;
                return false;
            }

            ofs.write(&body[0], body.size());
            if (ofs.good() == false)
            {
                std::cout << "write file error" << std::endl;
                ofs.close();
                return false;
            }

            ofs.close();
            return true;
        }
        bool GetPosLen(std::string* body, size_t pos, size_t len)
        {
            // 判断 pos + len 是否超出文件大小
            size_t size = FileSize();
            if (pos + len > size)
            {
                std::cout << "pos + len more than file size" << std::endl;
                return false;
            }

            // 读的形式打开文件
            std::ifstream ifs;
            ifs.open(_filename.c_str(), std::ios::binary);
            if (ifs.is_open() == false)
            {
                std::cout << "read open file error" << std::endl;
                return false;
            }

            // 打开成功后，先为body开辟足够的大小
            body->resize(len);

            // 从文件起始位置定位到pos位置
            ifs.seekg(pos, std::ios::beg);
            // 读取内容
            ifs.read(&(*body)[0], len);
            if (ifs.good() == false)
            {
                std::cout << "read file error" << std::endl;
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }

        bool GetContent(std::string* body)
        {
            size_t size = FileSize();
            return GetPosLen(body, 0, size);
        }

        bool Exists()
        {
            return std::experimental::filesystem::exists(_filename);
            std::experimental::filesystem::exists(_filename);
        }
        bool CreateDirectorys()
        {
            if (Exists() == true) return true;
            return std::experimental::filesystem::create_directories(_filename);
        }
        bool ScanDirectory(std::vector<std::string>* array)
        {
            for (auto& file : std::experimental::filesystem::directory_iterator(_filename))
            {
                if (std::experimental::filesystem::is_directory(file) == true)
                {
                    continue;
                }
                array->push_back(std::experimental::filesystem::path(file).relative_path().string());
            }
            return true;
        }
    private:
        std::string _filename;
    };
}

#endif
